package org.example.heterogeneous.readData;


import lombok.Data;
import org.example.heterogeneous.AdjacencyEdge;
import org.example.heterogeneous.Edge;
import org.example.heterogeneous.Node;
import org.example.heterogeneous.Utils;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/***
 * Effective and Efficient Truss Computation over Large Heterogeneous Information Networks 论文中的示例
 *
 */
@Data
public class TrussExample {

    private int start = 0;

    private int end = 0;

    // 输入的边
    private List<Edge> edgeList;

    // 输入的顶点集合
    private List<Node> nodeList;

    // 邻接表
    private List<AdjacencyEdge> adjacencyEdgeList;

    private int[] first;

    // A顶点类型为1
    public static final int A_TYPE = 1;

    // P顶点类型为2
    public static final int P_TYPE = 2;

    // T顶点类型为3
    public static final int T_TYPE = 3;

    // V顶点类型为4
    public static final int V_TYPE = 4;

    // 标识顶点是否已经存储
    Map<String, Integer> AExist;
    Map<String, Integer> PExist;
    Map<String, Integer> TExist;
    Map<String, Integer> VExist;

    // 标识边(x,y)是否已经存储
    Map<String, Boolean> edgeExist;

    private int index;

    public void read() {
        edgeList = new ArrayList<>();
        nodeList = new ArrayList<>();
        AExist = new HashMap<>();
        PExist = new HashMap<>();
        TExist = new HashMap<>();
        VExist = new HashMap<>();
        edgeExist = new HashMap<>();
        adjacencyEdgeList = new ArrayList<>();

        index = 0;
        readAP();
        readPT();
        readPV();
        end = nodeList.size();
        first = new int[end + 1];
        // 邻接表存储边
        adjacencyEdgeList = Utils.addEdge(edgeList, end, first);
    }

    public void readAP() {
        try {
            String inputFileName = "./src/main/java/org/example/heterogeneous/data/trussExampleAP.txt";
            String regex = "\t";
            BufferedReader reader = new BufferedReader(new FileReader(inputFileName));
            String line;
            String str;
            int x, y;
            int A_Index, P_Index;
            String A_Id, P_Id;

            while ((line = reader.readLine()) != null) {
                String[] words = line.split(regex);
                // 去掉格式不符合的数据
                if (words.length != 2) {
                    continue;
                }
                A_Id = words[0].trim();
                P_Id = words[1].trim();

                if (!AExist.containsKey(A_Id)) {
                    Node tempA = new Node(index++, A_TYPE, A_Id);
                    nodeList.add(tempA);
                    AExist.put(A_Id, tempA.getId());
                    A_Index = tempA.getId();
                } else {
                    A_Index = AExist.get(A_Id);
                }
                if (!PExist.containsKey(P_Id)) {
                    Node tempP = new Node(index++, P_TYPE, P_Id);
                    nodeList.add(tempP);
                    PExist.put(P_Id, tempP.getId());
                    P_Index = tempP.getId();
                } else {
                    P_Index = PExist.get(P_Id);
                }

                // A-P
                x = Math.min(A_Index, P_Index);
                y = A_Index ^ P_Index ^ x;
                str = x + "-" + y;
                // 去除重边
                if (!edgeExist.containsKey(str)) {
                    edgeExist.put(str, true);
                    edgeList.add(new Edge(x, y));
                }

            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void readPT() {
        try {
            String inputFileName = "./src/main/java/org/example/heterogeneous/data/trussExamplePT.txt";
            String regex = "\t";
            BufferedReader reader = new BufferedReader(new FileReader(inputFileName));
            String line;
            String str;
            int x, y;
            int P_Index, T_Index;
            String P_Id, T_Id;

            while ((line = reader.readLine()) != null) {
                String[] words = line.split(regex);
                // 去掉格式不符合的数据
                if (words.length != 2) {
                    continue;
                }
                P_Id = words[0].trim();
                T_Id = words[1].trim();

                if (!PExist.containsKey(P_Id)) {
                    Node tempP = new Node(index++, P_TYPE, P_Id);
                    nodeList.add(tempP);
                    PExist.put(P_Id, tempP.getId());
                    P_Index = tempP.getId();
                } else {
                    P_Index = PExist.get(P_Id);
                }
                if (!TExist.containsKey(T_Id)) {
                    Node tempT = new Node(index++, T_TYPE, T_Id);
                    nodeList.add(tempT);
                    TExist.put(T_Id, tempT.getId());
                    T_Index = tempT.getId();
                } else {
                    T_Index = TExist.get(T_Id);
                }


                // P-T
                x = Math.min(P_Index, T_Index);
                y = T_Index ^ P_Index ^ x;
                str = x + "-" + y;
                // 去除重边
                if (!edgeExist.containsKey(str)) {
                    edgeExist.put(str, true);
                    edgeList.add(new Edge(x, y));
                }

            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void readPV() {
        try {
            String inputFileName = "./src/main/java/org/example/heterogeneous/data/trussExamplePV.txt";
            String regex = "\t";
            BufferedReader reader = new BufferedReader(new FileReader(inputFileName));
            String line;
            String str;
            int x, y;
            int P_Index, V_Index;
            String P_Id, V_Id;

            while ((line = reader.readLine()) != null) {
                String[] words = line.split(regex);
                // 去掉格式不符合的数据
                if (words.length != 2) {
                    continue;
                }
                P_Id = words[0].trim();
                V_Id = words[1].trim();

                if (!PExist.containsKey(P_Id)) {
                    Node tempP = new Node(index++, P_TYPE, P_Id);
                    nodeList.add(tempP);
                    PExist.put(P_Id, tempP.getId());
                    P_Index = tempP.getId();
                } else {
                    P_Index = PExist.get(P_Id);
                }
                if (!VExist.containsKey(V_Id)) {
                    Node tempV = new Node(index++, V_TYPE, V_Id);
                    nodeList.add(tempV);
                    VExist.put(V_Id, tempV.getId());
                    V_Index = tempV.getId();
                } else {
                    V_Index = VExist.get(V_Id);
                }


                // P-V
                x = Math.min(P_Index, V_Index);
                y = V_Index ^ P_Index ^ x;
                str = x + "-" + y;
                // 去除重边
                if (!edgeExist.containsKey(str)) {
                    edgeExist.put(str, true);
                    edgeList.add(new Edge(x, y));
                }

            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}
